/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2014, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package org.geotools.brewer.styling.builder;

import javax.measure.Unit;
import javax.measure.quantity.Length;
import org.geotools.api.filter.expression.Expression;
import org.geotools.api.style.LineSymbolizer;
import org.geotools.api.style.OverlapBehaviorEnum;
import org.geotools.api.style.PolygonSymbolizer;
import org.geotools.api.style.RasterSymbolizer;
import org.geotools.api.style.Symbolizer;

public class RasterSymbolizerBuilder extends SymbolizerBuilder<RasterSymbolizer> {
    private String name;

    private Expression geometry;

    private DescriptionBuilder description = new DescriptionBuilder().unset();

    private Unit<?> uom;

    private Expression opacity;

    private ChannelSelectionBuilder channelSelection = new ChannelSelectionBuilder(this).unset();

    private ColorMapBuilder colorMap = new ColorMapBuilder(this).unset();

    private OverlapBehaviorEnum overlapsBehaviour;

    private ContrastEnhancementBuilder contrast = new ContrastEnhancementBuilder(this).unset();

    private ShadedReliefBuilder shadedRelief = new ShadedReliefBuilder(this).unset();

    private Builder<? extends Symbolizer> outline;

    public RasterSymbolizerBuilder() {
        this(null);
    }

    public RasterSymbolizerBuilder(AbstractStyleBuilder<?> parent) {
        super(parent);
        reset();
    }

    public RasterSymbolizerBuilder name(String name) {
        this.name = name;
        unset = false;
        return this;
    }

    public DescriptionBuilder description() {
        unset = false;
        return description;
    }

    public RasterSymbolizerBuilder geometry(Expression geometry) {
        this.geometry = geometry;
        this.unset = false;
        return this;
    }

    public RasterSymbolizerBuilder geometry(String cqlExpression) {
        return geometry(cqlExpression(cqlExpression));
    }

    public RasterSymbolizerBuilder opacity(Expression opacity) {
        this.opacity = opacity;
        this.unset = false;
        return this;
    }

    public RasterSymbolizerBuilder opacity(double opacity) {
        return opacity(literal(opacity));
    }

    public RasterSymbolizerBuilder opacity(String cqlExpression) {
        return opacity(cqlExpression(cqlExpression));
    }

    public RasterSymbolizerBuilder uom(Unit<Length> uom) {
        unset = false;
        this.uom = uom;
        return this;
    }

    public ChannelSelectionBuilder channelSelection() {
        unset = false;
        return channelSelection;
    }

    public ColorMapBuilder colorMap() {
        unset = false;
        return colorMap;
    }

    public ContrastEnhancementBuilder contrastEnhancement() {
        unset = false;
        return contrast;
    }

    public ShadedReliefBuilder shadedRelief() {
        unset = false;
        return shadedRelief;
    }

    public RasterSymbolizerBuilder overlapBehavior(OverlapBehaviorEnum behavior) {
        unset = false;
        this.overlapsBehaviour = behavior;
        return this;
    }

    @Override
    public RasterSymbolizer build() {
        if (unset) {
            return null;
        }
        RasterSymbolizer symbolizer =
                sf.rasterSymbolizer(
                        name,
                        geometry,
                        description.build(),
                        uom,
                        opacity,
                        channelSelection.build(),
                        overlapsBehaviour,
                        colorMap.build(),
                        contrast.build(),
                        shadedRelief.build(),
                        outline != null ? outline.build() : null);
        symbolizer.getOptions().putAll(options);
        return symbolizer;
    }

    @Override
    public RasterSymbolizerBuilder reset() {
        opacity = literal(1.0);
        channelSelection.unset();
        contrast.unset();
        unset = false;
        outline = null;
        return this;
    }

    @Override
    public RasterSymbolizerBuilder reset(RasterSymbolizer symbolizer) {
        if (symbolizer == null) {
            return reset();
        }
        opacity = symbolizer.getOpacity();
        channelSelection.reset(symbolizer.getChannelSelection());
        colorMap.reset(symbolizer.getColorMap());
        contrast.reset(symbolizer.getContrastEnhancement());
        if (symbolizer.getImageOutline() instanceof LineSymbolizer) {
            this.outline =
                    new LineSymbolizerBuilder()
                            .reset((LineSymbolizer) symbolizer.getImageOutline());
        } else if (symbolizer.getImageOutline() instanceof PolygonSymbolizer) {
            this.outline =
                    new PolygonSymbolizerBuilder()
                            .reset((PolygonSymbolizer) symbolizer.getImageOutline());
        }
        unset = false;
        return this;
    }

    @Override
    protected void buildStyleInternal(StyleBuilder sb) {
        sb.featureTypeStyle().rule().raster().init(this);
    }

    @Override
    public RasterSymbolizerBuilder unset() {
        return (RasterSymbolizerBuilder) super.unset();
    }
}
